package com.atguigu.gulimail.product.service.impl;

import com.atguigu.common.constant.ProductConstant;
import com.atguigu.gulimail.product.dao.AttrAttrgroupRelationDao;
import com.atguigu.gulimail.product.dao.AttrGroupDao;
import com.atguigu.gulimail.product.dao.CategoryDao;
import com.atguigu.gulimail.product.entity.AttrAttrgroupRelationEntity;
import com.atguigu.gulimail.product.entity.AttrGroupEntity;
import com.atguigu.gulimail.product.entity.CategoryEntity;
import com.atguigu.gulimail.product.service.CategoryService;
import com.atguigu.gulimail.product.vo.AttrGroupRelationVo;
import com.atguigu.gulimail.product.vo.AttrRespVo;
import com.atguigu.gulimail.product.vo.AttrVo;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimail.product.dao.AttrDao;
import com.atguigu.gulimail.product.entity.AttrEntity;
import com.atguigu.gulimail.product.service.AttrService;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {

    //自动的注入属性分组和属性的关联关系的对象
    @Autowired
    AttrAttrgroupRelationDao relationDao;
    @Autowired
    CategoryDao categoryDao;
    @Autowired
    AttrGroupDao attrGroupDao;
    @Autowired
    CategoryService categoryService;




    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public void saveAttr(AttrVo attr) {
        //创建一个AttrEntity对象
        AttrEntity  attrEntity  = new AttrEntity();
        //使用beanUtils工具类，进行属性复制
        //前端传递过来属性对象，复制给实体类属性分组对象，
        BeanUtils.copyProperties(attr,attrEntity);
        //把属性的pojo实体对象attrEntity进行保存到数据库中
        this.save(attrEntity);

        //如果是销售属性无需做group_id设置
        if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() && attr.getAttrGroupId()!=null){
            //保存关联关系
            //创建关联关系对象
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            //使用该关联实体对象进行把属性id和属性分组id进行到该实体对象中
            relationEntity.setAttrGroupId(attr.getAttrGroupId());
            relationEntity.setAttrId(attrEntity.getAttrId());
            //该关联对象保存到数据库中
            relationDao.insert(relationEntity);
        }
    }

    //根据商品分类id进行条件分页获取规格属性参数
    @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type) {

        //1创建条件构造器对象
        QueryWrapper<AttrEntity>  queryWrapper =  new QueryWrapper<AttrEntity>().eq("attr_type","base".equalsIgnoreCase(type)? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() : ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());
        //如果商品分类id==0 进行查询所有的规格参数
        if(catelogId !=0){
            //商品分类id不为0表示进行商品分类id进行查询
            queryWrapper.eq("catelog_id",catelogId);
        }
        //如果检索条件key 不为空进行检索条件进行查询
        //获取key 检索条件
        String key =  (String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            //使用条件构造进行构造查询条件
            //根据attr_id  attr_name这两个条件进行检索查询
            //where catelog_id= ? and(attr_id=   or  attr_name  like ?  )
            queryWrapper.and((wrapper) ->{
                wrapper.eq("attr_id",key).or().like("attr_name",key);
            });
        }

        //2当前的业务接口调用page方法进行分页查询，在将分页查询的数据封装成一个pageUtils工具类对象
        IPage<AttrEntity>  page =  this.page(
                new Query<AttrEntity>().getPage(params),
                queryWrapper
        );

        PageUtils pageUtils = new PageUtils(page);
        //使用page对象进行获取到分页记录数
        List<AttrEntity> records = page.getRecords();

        //使用查询的记录数进行流式处理，map进行数据操作，收集数据到集合中
        List<AttrRespVo> respvo = records.stream().map((attrEntity) -> {
            //创建属性分组响应vo实体视图对象
            AttrRespVo attrRespVo = new AttrRespVo();
            //使用BeanUtils工具类对象属性赋值操作2
            BeanUtils.copyProperties(attrEntity, attrRespVo);
            //1属性分组的和分类的名字进行设置到相应对象中去
            //根据关联对象调用条件查询单条记录获取关联对象
            AttrAttrgroupRelationEntity attr_id = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));

            //只有是基本属性设置属性  分组销售属性不做
            if("base".equalsIgnoreCase(type)){
                //判断如果获取关联对象不为空
                if (attr_id != null  && attr_id.getAttrGroupId() !=null) {
                    //属性分组名称设置到响应对象vo视图对象
                    //1先获取属性分组实体对象
                    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attr_id.getAttrGroupId());
                    //2属性分组名称设置到响应对象中去
                    attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }



            // 商品分类名称设置到响应对象中去
            //attr 属性分组表中有商品分类id 所以从商品分类dao根据商品分类id进行获取商品分类实体
            CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
            //进行判断商品分类实体不为空，查询有商品分类记录
            if (categoryEntity != null) {
                //商品分类名称进行设置到响应对象中
                attrRespVo.setCatelogName(categoryEntity.getName());
            }
            return attrRespVo;
        }).collect(Collectors.toList());
        pageUtils.setList(respvo);
        return  pageUtils;
    }

    //根据属性分组id进行属性视图响应对象
    @Override
    public AttrRespVo getAttrInfo(Long attrId) {
        //实例化分组的属性分组响应的视图vo对象
        AttrRespVo attrRespVo = new AttrRespVo();
        //根据属性的id获取属性分组实体
        AttrEntity attrEntity = this.getById(attrId);
        //使用BeanUtils工具类进行属性分组的复制属性分组响应的vo对象
        BeanUtils.copyProperties(attrEntity,attrRespVo);
        //进行属性的额分组的响应的视图对象设置 属性分组id  属性分组名称 商品分类id 商品分类的名称

        //1设置属性分组id  属性分组名称 先获取关联实体对象
        //根据条件attr_id进行查询
        //设置分组这里进行一次判断。销售添加数据失败（有attr_type决定该att表是基本属性表 还是销售属性表）
        if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            AttrAttrgroupRelationEntity relationEntity = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));

            //判断该关联实体对象非空，只有这样才可以把关联实体属性分组id和属性分组实体属性分组名称
            if(relationEntity != null){
                attrRespVo.setAttrGroupId(relationEntity.getAttrGroupId());
                //先获取属性分组实体对象  attrGroupDao.selectById()根据id进行查询，分组id从关联实体对象中进行获取
                AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
                if(attrGroupEntity != null){
                    //分组名称放置在attrRespVo实体对象
                    attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }


        }


        //关联实体对象中设置分类路径和分类地名称
        //先调用商品分类地业务接口地传递分类id获取商品父子路径
        Long[] catelogPath = categoryService.findCatelogPath(attrEntity.getCatelogId());
        //路径设置响应视图对象中
        attrRespVo.setCatelogPath(catelogPath);
        //查询商品分类实体，从商品分类实体地名称设置到vo 响应对象
        CategoryEntity categoryEntity = categoryService.getById(attrEntity.getCatelogId());
        //判断商品分类实体不为空
        if(categoryEntity !=null){
            //商品分类名称地设置vo 响应对象中
            attrRespVo.setCatelogName(categoryEntity.getName());
        }


        return attrRespVo;
    }

    //修改属性分组信息
    @Override
    public void updateAttr(AttrVo attr) {
        //进来
        //创建一个属性实体对象
        AttrEntity attrEntity = new AttrEntity();
        //2属性复制
        BeanUtils.copyProperties(attr,attrEntity);
        //修改属性表地属性分组 修改带有属性地id地属性实体
        this.updateById(attrEntity);





        //3修改关联关系表中地   属性分组id 属性id
        //这里进行一次判断如果如果该基本类型进行属性分组设置
        if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            //创建属性关联实例
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            //属性分组id 和属性id 设置到关联对象
            relationEntity.setAttrGroupId(attr.getAttrGroupId());
            relationEntity.setAttrId(attr.getAttrId());

            //按照指定条件进行修改
            //判断是新增还是修改，统计数据库里面有没有这个记录
            //按照条件进行查询统计数据库是否存在这条记录 ，统计结果大于0 有 修改操作， 否则 没有  新增操作
            Integer count = relationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
            if(count > 0){
                relationDao.update(relationEntity,new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",attr.getAttrId()));

            }else{
                relationDao.insert(relationEntity);
            }
        }


    }

    /*根据分组id获取所有的关联的分组属性
    * 1现在关联表中找到所有的attr_group_id对应attr_id的
    * 2根据找到的attr_id获取所有的分组属性
    *
    * */
    @Override
    public List<AttrEntity> getRelationAttr(Long attrgroupId) {
        //1在关联表中获取的group_id对应所有attr_id的关联list容器
        List<AttrAttrgroupRelationEntity>  relationEntities= relationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>()
                .eq("attr_group_id", attrgroupId));
        //对list容器的数据，进行map操作，获取relationEntities关联list容器中的每一个attr_id，attr_id收集成ids集合存储
        List<Long> attrIds = relationEntities.stream().map((relationEntity) -> {
            return relationEntity.getAttrId();
        }).collect(Collectors.toList());

        //使用attrService接口商品attrIds存储attrId的list容器进行调用listByIds获取list容器的attrId对应每一个attrEntity实体

       //这里进行非空判断，判断获取到所有的关联的属性分组id 可能是一个空的集合
        // SELECT attr_id,search_type,enable,value_type,show_desc,icon,catelog_id,value_select,attr_type,attr_name FROM pms_attr WHERE attr_id IN ( )
        if(attrIds == null || attrIds.size() == 0){
            return null;
        }
        Collection<AttrEntity> attrEntities = this.listByIds(attrIds);
        //转换成list<AttrEntity>类型
        return (List<AttrEntity>) attrEntities;
    }
    //删除属性分组和属性之间的关联关系
    @Override
    public void deleteRelation(AttrGroupRelationVo[] vos) {
        //属性在属性表中并没有被删除，只是删除掉属性关联表中关联关系
        //DELETE FROM `pms_attr_attrgroup_relation`  WHERE
        //(attr_id = 1 and attr_group_id =1)  or
        // (attr_id = 2 and attr_group_id =3) OR (attr_id = 1 and attr_group_id =1)
        //创建一个前端发起一个请求传递过来【attr_id,attrGroupId,.....】数组，进行批量的删除关联关系
        List<AttrAttrgroupRelationEntity> relationEntites = Arrays.asList(vos).stream().map((item) -> {
            //把页面传递过来的数组进行流式处理，把里面数组里面group_id 和attr_id属性复制给关联关系的vo实体对象
            //创建关联实体对象
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            //属性的赋值
            BeanUtils.copyProperties(item, relationEntity);
            return relationEntity;
        }).collect(Collectors.toList());
        //上面relationEntities关联关系list容器，里面group_id和attr_id赋值前端传来这两个值
        //关联关系表的dao接口调用deleteBatchRelation()方法
        relationDao.deleteBatchRelation(relationEntites);
    }
    /*
    *
    * 获取那个分组下没有进行关联的属性
    * */
    @Override
    public PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId) {
        //当前分组只能关联自己所属分类 把当前分组的下所有属性进行排除
        //找到当前分组所有属性
        AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupId);
        //获取当前分组下的  商品分类
        Long catelogId = attrGroupEntity.getCatelogId();
        //2当前分组只能关联其他分组没有引用的属性
        //2.1当前分类下的所有分组 这些分组 除掉自己分组
        List<AttrGroupEntity> attrGroupEntities = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>()
                .eq("catelog_id", catelogId));

        //获取商品分类 其他分组id 组成list容器
        List<Long> otherGroupIds = attrGroupEntities.stream().map((item) -> {
            return item.getAttrGroupId();
        }).collect(Collectors.toList());
        //2.2这些分组关联属性
        //查出所有其他分组的实体拿到
        List<AttrAttrgroupRelationEntity> relationEntities = relationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>()
                .in("attr_group_id", otherGroupIds));
        //拿到其他所有分组的所有属性id组成的list容器
        List<Long> otherAttrIds = relationEntities.stream().map((item) -> {
            return item.getAttrId();
        }).collect(Collectors.toList());
        //2.3从当前分类的所有属性中移除这些属性
        //查找本分类下的 排除上面的本分类下的其他分组所有的属性 ，剩下就是自己分组下的其他属性


        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>().eq("catelog_id", catelogId)
                .eq("attr_type",ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());

        //进行判断
        if(otherAttrIds !=null  && otherAttrIds.size() > 0){
            //进行notIn查询
            wrapper.notIn("attr_id", otherAttrIds);
        }
        //模糊查询进行判断
        //从分页参数查询内容key
        String key  = (String) params.get("key");
        //进行判断
        if(!StringUtils.isEmpty(key)){
            wrapper.and((w) -> {
                w.eq("attr_id",key).or().like("attr_name",key);
            });
        }


        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), wrapper);
        //进行分组
        PageUtils pageUtils = new PageUtils(page);
        return  pageUtils;
    }

}